home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-30 | 8.6 KB | 315 lines | [TEXT/ttxt] |
- FUNCTION:
-
- This help file covers several aspects of functions:
-
- 1) Introduction
-
- 2) Function arguments
-
- 3) Function return values
-
- 4) Function recursion
-
- 5) Function variable scoping
-
- 6) Special topics
-
- 1) Introduction ------------------------------------------------
-
- Functions are an essential part of the language. Learning how
- to create and use functions will greatly add to the benefits
- of using RLaB.
-
- It is important to remember that functions adhere to the RLaB
- rule: "everything is a variable". Functions are variables, and
- like the other types or classes of variables in RLaB can be
- printed (although it will be hard to understand the output),
- copied, and renamed. Functions cannot act as operands to
- numeric operators, although the result of the function usually
- can. Since function calls are evaluated "in-place" they can be
- used within other expressions, for example:
-
- > sin(cos(1.0))
- 0.514
-
- > sin( [ cos(0.3), sqrt(cos(0.3)) ] )
- 0.817 0.829
-
-
- The syntax used for function definition is a little unusual...
-
- Example:
-
- > sum = function (s)
- {
- local(i, Sum);
- Sum = 0;
- for(i in 1:size(s)) {
- Sum = Sum + s[i];
- }
- return Sum;
- };
- >
-
- creates a function, and assigns it to the variable `sum'.
- Sum is invoked like:
-
- > sum( [1,2,3,4,5] )
- 15
-
- 2) Function arguments ------------------------------------------
-
- RLaB supports both "pass by reference" and "pass by value" for
- passing arguments to a function.
-
- Pass by reference means that the argument can be modified in
- the caller's scope. Pass by value means that a function cannot
- modify variables in the caller's scope - essentially, an
- argument that is passed by value is copied, and the copied
- value is passed to the function to operate on.
-
- Pass by reference can be considered the default behavior,
- since it takes no special effort on the user's part. Pass by
- value is achieved by declaring function arguments to be
- local. For example:
-
- // Pass by reference
-
- > myf = function ( A ) { A = "changed"; return A; }
- <user-function>
- > B=10;
- > myf(B);
- > B
- B =
- changed
-
- // Pass by value
- > myf = function ( A ) { local (A) A = "changed"; return A; }
- <user-function>
- > B=10;
- > myf(B);
- > B
- B =
- 10
-
- In the previous example B, a variable in the global workspace,
- is changed by myf (pass by reference). In the second part of
- the example, the function argument A, is redeclared to be
- local. This redeclaration forces the function argument to be
- passed by value.
-
- One advantage of this behavior is that users can create
- functions and selectively decide which variables should be
- passed by reference, and which should be passed by value.
-
- * * *
-
- You do not have to call a function with the same number of
- arguments specified in the definition. If you invoke a
- function with more arguments than declared, the result is an
- error. If you call the function with less arguments than
- declared, RLaB will pad the argument list with UNDEFINED,
- objects. Additionally, commas may be used to "skip" arguments
- that are unnecessary. for each argument that is "skipped" an
- UNDEFINED variable is passed to the function during execution.
-
- UNDEFINED arguments can be detected with the exist function,
- for example:
-
- if (!exist (ARG))
- {
- ARG = 0; // Initialize undefined argument
- }
-
- * * *
- Lists can be used to get the effect of variable argument
- lists. If you are not familiar with lists, then now would be a
- good time to `help LIST'. A function can take a list as an
- argument and then pull the actual number of list elements, and
- their values, from the list when the function is called. For
- example:
-
- > vlistf = function( l )
- {
- local(i,x);
-
- printf( "number of elements in variable arg-list = %i\n", size(l) );
-
- // Pull each element from the list
-
- for( i in 1:size(l) )
- {
- x = l.[i];
- // now do something with x
- }
- };
- > vlistf( << "string"; [1,2;3,4] >> )
- number of elements in variable arg-list = 2
-
- * * *
-
- Functions can take other functions as arguments, for example:
-
- > trick = function ( a , b )
- {
- a(b)
- };
- > trick( eye, [3,3] );
- matrix columns 1 thru 3
- 1 0 0
- 0 1 0
- 0 0 1
-
- Note that the function name, passed as an argument, did not
- need quotes. This is so because functions are variables in the
- same sense as scalars, strings, and matrices. The variable a
- in the previous function example refers to the function eye,
- since function args are passed by reference.
-
- 3) Function return values --------------------------------------
-
- All functions return a value, although the return statement is
- optional. If a return statement is not used, then the function
- will return 0 (zero) to the calling environment. If the return
- statement is used, the the result of the return statement is
- passed back to the calling environment.
-
- Functions can only return a single entity to the calling
- environment. If it is necessary to return more than one
- entity, a list can be used to group multiple entities together
- for return.
-
- Example:
-
- We want to write a function that creates a set of matrices (a
- state-space model). We will write such a function, and group
- the separate matrices together in a list.
-
- > ss = function( w )
- {
- local(A, B, n);
- n = size( w )[1];
- A = [ zeros(n,n), eye(n,n);
- -w; zeros(n,n) ];
- B = ones(n,n);
-
- return << A = A; B = B >>;
- };
- >
-
- The return statement creates the list, and assign the names
- `A' and `B' to it's members.
-
- Since functions are evaluated "in-place" their return values
- can be manipulated in the usual ways, for example:
-
- > eig(symm(rand(3,3))).val
- val =
- -0.937 0.571 1.81
-
- > eig(symm(rand(3,3))).val[2]
- 0.191
-
- > rand(10,10)[1,3,5;2,4,6]
- 0.29 0.411 0.345
- 0.561 0.686 0.0287
- 0.269 0.324 0.57
-
- 4) Function recursion ------------------------------------------
-
- Functions can call themselves recursively. Since a function is
- stored in the same manner as a variable, the function can be
- deleted, or renamed. Therefore, users must be careful not to
- rename functions that call themselves or they must use the
- `$self' keyword.
-
- Example:
-
- > fact = function (f)
- {
- if(f <= 1) {
- return 1;
- else
- return f*$self(f-1);
- }
- };
- > fact(10)
- 3628800
-
- 5) Function variable scoping -----------------------------------
-
- All function variables are GLOBAL by default. Since builtin
- and user-functions are treated like ordinary variables this
- ensures that user-functions have full access to existing
- builtin and user functions. If you need local variables, use
- the local statement at the beginning of your function.
-
- Example:
-
- > x = function(y)
- {
- local(i);
- for( i in 1:y.n ) {
- y[i] = 0;
- }
- return y;
- };
- >
-
- The local statement declares `i' to be a local scalar variable
- with initial value UNDEFINED. When the function returns the
- variable `i' will cease to exist. When x() is called again `i'
- will again be re-initialized UNDEFINED. The local statement
- must be the 1st statement in a function, and only one local
- statement is allowed. If you must declare alot of local
- variables, then break the local statement with a continuation.
-
- local(i, j, k,...
- l, m, n);
-
- Local variables are resolved 1st. When a name collision occurs
- between a local variable, and a global variable, including
- builtin functions, the local variable takes precedence.
-
- 6) Special Topics ----------------------------------------------
-
- A) Although pass by value is the default behavior for
- function arguments, there are some instances where
- this may not seem true (but it is). For example, when
- you pass part of a matrix into a function you cannot
- modify the original matrix.
-
- > x = function ( a ) { a[1] = pi; }
- <user-function>
- > z=rand(2,2);
- > z
- z =
- 0.0369 0.665
- 0.162 0.0847
- > x(z);
- > z
- z =
- 3.14 0.665
- 0.162 0.0847
- > x(z[2]);
- > z
- z =
- 3.14 0.665
- 0.162 0.0847
- > y
- UNDEFINED
- > x(y=z[2]);
- > y
- y =
- 3.14
-
- You can see that in the first function call, z is
- passed by reference. In the second call, the second
- element of z (z[2]) is copied into a temporary
- variable, which in turn is passed by reference to the
- function. In the last call the temporary variable is
- stored in the variable y, which as you can see, is
- passed by reference to the function for modification.
-
- ----------------------------------------------------------------
-